﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEditor;
using LitJson;

public class AssetBundleTools
{
    static string[] sceneFilters = new string[] { "XLua" }; 
   
    #region ==================Set AssetBundle Labels=====================
    [MenuItem("Assets/DNTools/Set AssetBundle Labels",false,180)] 
    public static void CreateAssetBundle()
    {
        string path = Application.dataPath.Replace("\\", "/");
        path += "/Res";
        if (!Directory.Exists(path)) Directory.CreateDirectory(path);
        DirectoryInfo directoryInfo = new DirectoryInfo(path);
        OnFildInfo(directoryInfo);
        Debug.Log("==========================AssetBundle设置成功===============================");

        
    }
    static void OnFildInfo(DirectoryInfo directoryInfo)
    {
        FileInfo[] fileInfos = directoryInfo.GetFiles();
        string appPath = Application.dataPath+ "/Res/";
        foreach (FileSystemInfo fileInfo in fileInfos)
        {
            if(fileInfo.Extension.Equals(".meta")) continue;
            string assetBundleName = fileInfo.FullName.Replace("\\","/").Replace(appPath, "");
            int index = assetBundleName.LastIndexOf("/");
            assetBundleName = assetBundleName.Substring(assetBundleName.IndexOf("/")==0 ? 1 : 0 , index);
            index = fileInfo.FullName.IndexOf("Assets");
            string assetpath = fileInfo.FullName.Substring(index);
            assetpath = assetpath.Replace("\\", "/");
            //设置 assetBundle 资源 labels
            AssetImporter assetImporter = AssetImporter.GetAtPath(assetpath);
            assetImporter.assetBundleName = assetBundleName.ToLower();
            if (fileInfo.Extension.Equals(".unity")) assetImporter.assetBundleVariant = "u3d";
            else assetImporter.assetBundleVariant = "assetBundle";
            Debug.Log("资源【"+ assetBundleName + "】设置成功...");
        }
        DirectoryInfo[] dirInfos= directoryInfo.GetDirectories();
        foreach (DirectoryInfo dirInfo in dirInfos)
        {
            OnFildInfo(dirInfo);
        }

    }
    #endregion

    #region ==================BuildTarget=====================
    [MenuItem("Assets/DNTools/BuildTarget/Android", false,180)]
    public static void BuildAssetBundlesAndroid()
    {
        
        BuildAssetBundles(BuildTarget.Android);
    }
    [MenuItem("Assets/DNTools/BuildTarget/IOS", false,181)]
    public static void BuildAssetBundlesIOS()
    {
        BuildAssetBundles(BuildTarget.iOS);
    }
    //[MenuItem("Assets/AssetBundle/BuildTarget/StandaloneWindows", false, 12)]
    //public static void BuildAssetBundlesStandaloneWindows()
    //{
    //    BuildAssetBundles(BuildTarget.StandaloneWindows);
    //}
    //[MenuItem("Assets/AssetBundle/BuildTarget/StandaloneWindows64", false, 13)]
    //public static void BuildAssetBundlesStandaloneWindows64()
    //{
    //    BuildAssetBundles(BuildTarget.StandaloneWindows64);
    //}

    static void BuildAssetBundles(BuildTarget buildTarget,bool showTips=true)
    {
        string outputPath = GetOutPath();
        outputPath +=  "/"+ buildTarget.ToString()+"/";
        if (!Directory.Exists(outputPath)) Directory.CreateDirectory(outputPath);
        AssetDatabase.Refresh();
        BuildPipeline.BuildAssetBundles(outputPath, 0, buildTarget);
        AssetDatabase.Refresh();
        Debug.Log("AssetBundle 打包完成......");
        if(showTips) EditorUtility.DisplayDialog("提示", "AssetBundle 打包成功", "确定");
    }

    #endregion

    #region ==================一键删除assetbundle文件=====================
    [MenuItem("Assets/DNTools/BuildTarget/Delete All(慎重)", false, 185)]
    static void DeleteAllFiles()
    {
        string outpath = GetOutPath();

        Directory.Delete(outpath, true);
        File.Delete(outpath + ".meta");
        
        Debug.Log("删除完成");
        if(EditorUtility.DisplayDialog("提示", "删除完成", "确定"))
        {
            AssetDatabase.Refresh();
        }
    }
    #endregion


    [MenuItem("Assets/DNTools/BuildTarget/CreateHotConfig", false, 182)]
    static void CreateHotConfig()
    {
        string path = GetOutPath();
        DirectoryInfo directoryInfo = new DirectoryInfo(path);
        JsonData jsonDataList = new JsonData();
        FildChangeFiles(directoryInfo, path, jsonDataList);
        JsonData jsonData=new JsonData();
        jsonData["version"] = "1.0.0";
        jsonData["hotFixFileDatas"] = jsonDataList;
        string jsonContent=JsonMapper.ToJson(jsonData);
        string outPath= GetOutPath();
        outPath += "/Fininfo.json";
        SaveFile(outPath, jsonContent);
        Debug.Log("文件【" + outPath + "】保存完成");
        if (EditorUtility.DisplayDialog("提示", "文件写入完成", "确定"))
        {
            AssetDatabase.Refresh();
            EditorUtility.RevealInFinder(outPath);
        }
    }
    static void SaveFile(string outPath,string content)
    {
        File.WriteAllText(outPath, content);
    }
    static void FildChangeFiles(DirectoryInfo info,string rootPath, JsonData jsonData)
    {
        FileInfo[] files = info.GetFiles();
        foreach (FileInfo file in files)
        {
            if (file.Extension.Equals(".meta")) continue;
            string filePath=file.FullName.Replace("\\","/");
            string dir = filePath.Replace(rootPath+"/","");
            string[] fileNameArr = dir.Split('/');
            string fileName = fileNameArr[fileNameArr.Length - 1];
            string fileMd5 = CryptoUnit.MD5(file.LastWriteTimeUtc.Ticks.ToString());
            dir = dir.Replace(fileName,"");
            JsonData itemData=new JsonData();
            itemData["filename"] = fileName;
            itemData["dir"] = dir;
            itemData["MD5"] = fileMd5;
            itemData["httpDir"] = "";
            jsonData.Add(itemData);
        }
        DirectoryInfo[] directories= info.GetDirectories();
        foreach (DirectoryInfo directory in directories) FildChangeFiles(directory,rootPath, jsonData);
    }

    [MenuItem("Assets/DNTools/CopyAssetBundleToStream", false, 100)]
    static void CopyAssetBundleToStream()
    {
        string outpath = GetOutPath();
        string inPath = Application.streamingAssetsPath;
        if(!Directory.Exists(inPath)) Directory.CreateDirectory(inPath);
        CopyOldLabFilesToNewLab(outpath, inPath);
        Debug.Log("文件复制完成!");
        if (EditorUtility.DisplayDialog("提示", "文件复制完成", "确定"))
        {
            AssetDatabase.Refresh();
          //  EditorUtility.RevealInFinder(inPath);
        }
    }
    [MenuItem("Assets/DNTools/CopyLuaScripsToAssetBundleDir", false, 20)]
    static void CopyLuaScripsToDist()
    {
        string outPath = Application.dataPath.Replace("\\", "/") + "/LuaScripts";
        string inPath= Application.dataPath.Replace("\\", "/")+ "/Res/LuaScripts";
        if (!Directory.Exists(inPath)) Directory.CreateDirectory(inPath);
        CopyOldLabFilesToNewLab(outPath, inPath,".txt");
        Debug.Log("Lua脚本复制完成!");
        if (EditorUtility.DisplayDialog("提示", "Lua脚本复制完成", "确定"))
        {
            AssetDatabase.Refresh();
            //EditorUtility.RevealInFinder(inPath);
        }
    }
    [MenuItem("Assets/DNTools/DeleteCopyLuaScripsDir", false, 21)]
    static void DeleteCopyLuaScrips()
    {
        string outpath = Application.dataPath.Replace("\\", "/") + "/Res/LuaScripts";

        Directory.Delete(outpath, true);
        File.Delete(outpath + ".meta");
        Debug.Log("删除LuaScrip脚本完成");
        if (EditorUtility.DisplayDialog("提示", "删除LuaScrip脚本完成", "确定"))
        {
            AssetDatabase.Refresh();
        }
    }
    /// <summary>
    /// 拷贝oldlab的文件到newlab下面
    /// </summary>
    /// <param name="sourcePath">lab文件所在目录(@"~\labs\oldlab")</param>
    /// <param name="savePath">保存的目标目录(@"~\labs\newlab")</param>
    /// <returns>返回:true-拷贝成功;false:拷贝失败</returns>
    static bool CopyOldLabFilesToNewLab(string sourcePath, string savePath,string suffix="")
    {
        if (!Directory.Exists(savePath))
        {
            Directory.CreateDirectory(savePath);
        }

        #region //拷贝labs文件夹到savePath下
        try
        {
            string[] labDirs = Directory.GetDirectories(sourcePath);//目录
            string[] labFiles = Directory.GetFiles(sourcePath);//文件
            if (labFiles.Length > 0)
            {
                for (int i = 0; i < labFiles.Length; i++)
                {
                    if (Path.GetExtension(labFiles[i]) != ".meta")//排除.meta文件
                    {
                        string dstPath = savePath + "\\" + Path.GetFileName(labFiles[i]);
                        if(!string.IsNullOrEmpty(suffix))
                        {
                            dstPath= dstPath.Substring(0, dstPath.IndexOf("."));
                            dstPath += suffix;
                        }
                        File.Copy(sourcePath + "\\" + Path.GetFileName(labFiles[i]), dstPath, true);
                    }
                }
            }
            if (labDirs.Length > 0)
            {
                for (int j = 0; j < labDirs.Length; j++)
                {
                    if (labDirs[j].IndexOf(".vscode") >= 0) continue;
                    Directory.GetDirectories(sourcePath + "\\" + Path.GetFileName(labDirs[j]));

                    //递归调用
                    CopyOldLabFilesToNewLab(sourcePath + "\\" + Path.GetFileName(labDirs[j]), savePath + "\\" + Path.GetFileName(labDirs[j]), suffix);
                }
            }
        }
        catch (System.Exception)
        {
            return false;
        }
        #endregion
        return true;
    }



    #region ==================Scene Add To Setting=====================
    [MenuItem("Assets/DNTools/Scene Add To Setting", false, 200)]
    public static void SceneAddToSetting()
    {
        string path = Application.dataPath;
        List<string> unityList=new List<string>();
        string[] allFiles = FileUnit.GetDirFiles(path);
        for (int i = 0; i < allFiles.Length; i++)
        {
            if (allFiles[i].LastIndexOf(".unity") >= 0 && !HasSceneFilters(allFiles[i]))
            {
                if (
                   allFiles[i].LastIndexOf("Main") >= 0 || allFiles[i].LastIndexOf("main") >= 0 ||
                   allFiles[i].LastIndexOf("Load") >= 0 || allFiles[i].LastIndexOf("load") >= 0
                   )
                {
                    unityList.Insert(0, allFiles[i]);
                }
                else 
                    unityList.Add(allFiles[i]);
            }
        }
       
        EditorBuildSettingsScene[] editorBuildSettingsScenes = new EditorBuildSettingsScene[unityList.Count];
        for(int i = 0; i < unityList.Count; i++)
        {
            string scenepath= unityList[i].Replace("\\","/");
            int index = scenepath.IndexOf("Assets");
            scenepath = scenepath.Substring(index);
            editorBuildSettingsScenes[i] = new EditorBuildSettingsScene(scenepath, true);
        }
        EditorBuildSettings.scenes = editorBuildSettingsScenes;
        Debug.Log("场景添加到设置完成");
        EditorUtility.DisplayDialog("提示", "场景添加到设置完成", "确定");
    }

    #endregion


    [MenuItem("Assets/DNTools/Build Platform", false, 220)]
    public static void BuildPlayer()
    {
        var outputPath = EditorUtility.SaveFolderPanel("Choose Location of the Built Game", "", "");
        if (outputPath.Length == 0)
            return;

        string[] levels = GetLevelsFromBuildSettings();
        if (levels.Length == 0)
        {
            Debug.Log("Nothing scene item to build.");
            return;
        }
        EditorBuildSettingsScene[] editorBuildSettingsScenes = new EditorBuildSettingsScene[levels.Length];
        for (int i = 0; i < levels.Length; i++)
        {
            editorBuildSettingsScenes[i] = new EditorBuildSettingsScene(levels[i], true);
        }
        EditorBuildSettings.scenes = editorBuildSettingsScenes;

        string fileName = "/" + Application.productName;
        string targetName = GetBuildTargetName(EditorUserBuildSettings.activeBuildTarget, fileName);
        if (targetName == null)
            return;

        BuildAssetBundles(EditorUserBuildSettings.activeBuildTarget,false);
        string outPath = outputPath + targetName;
        BuildOptions option = EditorUserBuildSettings.development ? BuildOptions.Development : BuildOptions.None;
        BuildPipeline.BuildPlayer(levels, outPath, EditorUserBuildSettings.activeBuildTarget, option);
        if(EditorUtility.DisplayDialog("提示", "平台打包成功", "确定"))
        {
            EditorUtility.RevealInFinder(outPath);
        }
    }
    static string GetBuildTargetName(BuildTarget target,string fileName)
    {
        switch (target)
        {
            case BuildTarget.Android:
                return fileName+".apk";
            case BuildTarget.StandaloneWindows:
            case BuildTarget.StandaloneWindows64:
                return fileName+".exe";
            case BuildTarget.StandaloneOSX:
                return fileName+"test.app";
            case BuildTarget.WebGL:
                return "";
            // Add more build targets for your own.
            default:
                Debug.Log("Target not implemented.");
                return null;
        }
    }
    static string[] GetLevelsFromBuildSettings()
    {
        List<string> levels = new List<string>();
        for (int i = 0; i < EditorBuildSettings.scenes.Length; ++i)
        {
            if (EditorBuildSettings.scenes[i].enabled)
                levels.Add(EditorBuildSettings.scenes[i].path);
           
        }
        return levels.ToArray();
    }
    /// <summary>
    /// 验证场景过滤文件
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    static bool HasSceneFilters(string path)
    {
        for(int i=0;i< sceneFilters.Length; ++i)
        {
            if (path.IndexOf(sceneFilters[i]) >= 0) return true;
        }
        return false;
    }
    static string GetOutPath()
    {
        string outpath = Application.dataPath;
        outpath = outpath.Replace("Assets", "");
        outpath += "AssetBundle";
        return outpath;
    }
}
